/*不定参的使用*/

// #define _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>

// 在 C/C++ 中，相邻的字符串字面量会自动合并，但必须用空格分隔
// __VA_ARGS__ 用于展开宏定义中 ... 部分传递的所有参数

// #define ARGS(format, ...) printf("[%s:%d]" format, __FILE__, __LINE__, __VA_ARGS__)
#define ARGS(format, ...) printf( "[%s:%d]" format, __FILE__, __LINE__, ##__VA_ARGS__)

// ## 是为了处理没有不定参的情况，也就是...为空的情况
// 因为如果...不传，printf函数最后会多一个","
// 加上##就是告诉编译器：一旦不定参为空，则取消前面的","

// int main()
// {
//     // printf("[%s:%d] %sand%s\n", __FILE__, __LINE__, "甘雨", "丝柯克");
//     ARGS("%sand%s\n", "甘雨", "丝柯克");
//     ARGS("我好帅\n");
//     return 0;
// }



/*C语言中不定参函数的使用，不定参数据的访问*/
#include <stdarg.h>

/*
va_list	            定义参数列表的指针类型（本质是 char*）
va_start(ap, last)	初始化 va_list，last 是最后一个固定参数名
va_arg(ap, type)	从参数列表中读取一个 type 类型的值，并移动指针到下一个参数
va_end              将指针置空
*/
void printNum(int count, ...)
{
    va_list ap;
    va_start(ap, count);
    
    int n = 0;
    while(n++ < count)
    {
        ARGS("第%d个数字是: %d\n", n, va_arg(ap, int));
    }
    va_end(ap);
}


void myprintf(char* format, ...)
{
    va_list ap;
    va_start(ap,format);
    char* res;

    //字符串的解析工作不需要我们自己来处理
    //有现成的函数可以调用: vasprintf

    //他会将解析好的字符串放入一段开辟的空间，res指向这段空间
    //因此最后不要忘了释放res
    if(vasprintf(&res, format, ap) != -1)
        printf(res);
    free(res);
}

// int main()
// {
//     printNum(5, 122,3,5324,213,63);
//     myprintf("%sand%s\n", "甘雨", "丝柯克");
//     return 0;
// }



/*C++中不定参函数的使用，不定参数据的访问*/
#include <iostream>
// void _printf()
// {
//     std::cout << "参数包解析完毕" <<std::endl;
// }
// template<class T, class ...Args>
// void _printf(const T& val, Args ...args)
// {
//     std::cout << val << " ";
//     _printf(args...);
// }
// template<class T, class ...Args>
// void cppPrintf(const T& val, Args ...args)
// {
//     std::cout << val << " ";
//     _printf(args...);
// }

void _cppPrintf()
{
    std::cout << "参数包解析完毕" << std::endl << std::endl;
}
template<class T, class ...Args>
void _cppPrintf(const T& val, Args&& ...args)
{
    std::cout << val << std::endl;
    _cppPrintf(std::forward<Args>(args)...);
}
template<class ...Args>
void cppPrintf(Args&& ...args)
{
    std::cout << "开始解析参数包" << std::endl;
    _cppPrintf(std::forward<Args>(args)...);
}

int main()
{
    cppPrintf("我是谁", 3.141592653, 56, "吃饭了吗");
    return 0;
}

